package models;

import java.util.ArrayList;

public class Model {
	// root node, assuming root node can't have siblings
	ModelNode root;
	// edges, maybe
	
	// id counter
	int idCounter = 1;
	
	public Model(ModelNode root){
		this.root = root;
		this.root.setId(0);
	}
	
	public void addNodeToLastAddedNode(ModelNode node){
		ModelNode tempNode = getLastNode();
		node.setId(idCounter++);
		tempNode.addChild(node);
	}
	
	/**
	 * Adds the node to the node that is last(that is the leaf node that lies the deepest)
	 * @param node
	 * @return
	 */
	public void addNodeLast(ModelNode node){
		ModelNode deepestNode = null;
		getDeepestNode(root, 1, 0, deepestNode);
		node.setId(idCounter++);
		deepestNode.addChild(node);
	}
	
	// TODO: FIX, passes "by value" so the targetNode does not get updated and sent back
	private void getDeepestNode(ModelNode node, int currentDepth, int currentMax,
			ModelNode targetNode){
		int max = currentMax;
		if(currentDepth > currentMax){
			targetNode = node;
			max = currentDepth;
		}
		for(ModelNode child : node.getChildren()){
			getDeepestNode(child, currentDepth+1, max, targetNode);
		}
	}
	
	
	/**
	 * finds the depth from the node to the bottom of the branch
	 * @param node
	 * @param currentDepth
	 * @return
	 */
	private int depthOfBranch(ModelNode node, int currentDepth){
		int max = currentDepth;
		for(ModelNode child : node.getChildren()){
			int temp = depthOfBranch(child, currentDepth+1);
			if(temp > max){
				max = temp;
			}
		}
		return max;
	}
	
	/**
	 * Adds the node as child to the specific ModelNode
	 * @param node
	 * @param parent
	 * @return
	 */
	public void addNodeAsChildTo(ModelNode node, ModelNode parent){
		node.setId(idCounter++);
		parent.addChild(node);
	}
	
	public boolean addNodeAsChildTo(ModelNode node, int parentID){
		ModelNode parentNode = getNode(parentID);
		if(parentNode == null){
			return false;
		}
		node.setId(idCounter++);
		parentNode.addChild(node);
		return true;
	}
	
	/**
	 * Gets the node with the highest id, the node that was added most recently
	 * @return
	 */
	public ModelNode getLastNode(){
		return getNode(idCounter-1);
	}
	
	/**
	 * Gets the node with the id "nodeID"
	 * @param nodeID
	 * @return ModelNode, null if node not found
	 */
	public ModelNode getNode(int nodeID){
		return findNode(root, nodeID);
	}
	
	/**
	 * finds the node with the id "nodeID" if it exists, null otherwise
	 * @param checkNode
	 * @param nodeID
	 * @return
	 */
	private ModelNode findNode(ModelNode checkNode, int nodeID){
		if(checkNode.getId() == nodeID){
			return checkNode;
		}
		ModelNode foundNode = null;
		for(ModelNode child : checkNode.getChildren()){
			foundNode = findNode(child, nodeID);
			if(foundNode != null)
				break;
		}
		return foundNode;
	}
	
	/**
	 * Gets the parent of the node "node"
	 * @param node
	 * @return
	 */
//	public ModelNode parentOf(ModelNode node){
//		
//	}
}
